﻿using CoreHelper.Reflection;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Collections.Concurrent;

namespace CoreHelper.AppEvent
{
    /// <summary>
    /// 应用程序事件管理器
    /// </summary>
    public static class AppEventManager
    {
        static ConcurrentDictionary<string, Func<object[], object>> eventHandlerDict = new ConcurrentDictionary<string, Func<object[], object>>();

        /// <summary>
        /// 添加事件处理程序
        /// </summary>
        /// <param name="eventKey"></param>
        /// <param name="func"></param>
        public static void AddHandler(string eventKey, Func<object[], object> func)
        {
            eventHandlerDict.AddOrUpdate(eventKey, func, (key, oldFun) =>
            {
                return oldFun += func;
            });
        }

        /// <summary>
        /// 触发事件
        /// </summary>
        /// <param name="eventKey"></param>
        /// <param name="ps"></param>
        /// <returns></returns>
        public static Task Fire(string eventKey, params object[] ps)
        {
            if (eventHandlerDict.TryGetValue(eventKey, out Func<object[], object> func))
            {
                return Task.Run(() => func(ps));
            }
            else
            {
                return Task.CompletedTask;
            }
        }

        /// <summary>
        /// 扫码程序集，注册事件处理程序
        /// </summary>
        /// <param name="assembly"></param>
        public static void ScanEventHandler(Assembly assembly)
        {
            foreach (var type in assembly.GetTypes())
            {
                var methodInfos = type.GetMethods(BindingFlags.Static | BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic ^ BindingFlags.GetProperty ^ BindingFlags.SetProperty);

                foreach (var methodInfo in methodInfos)
                {
                    var mehAttr = methodInfo.GetCustomAttribute<AppEventHandlerAttribute>();
                    if (mehAttr != null)
                    {
                        var fun = DynamicMethodHelper.GetExecuteDelegate(methodInfo);

                        AddHandler(mehAttr.EventKey, (args) =>
                        {
                            return fun(methodInfo.IsStatic ? null : Activator.CreateInstance(type), args);
                        });
                    }
                }
            }
        }
    }
}
